---
title: Transitions de vue
description: Permettre une navigation fluide entre les pages dans Astro grâce aux transitions de vue.
i18nReady: true
---
import ReadMore from '~/components/ReadMore.astro'
import Since from '~/components/Since.astro'
import { Steps } from '@astrojs/starlight/components'

Les [transitions de vue](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API) sont des transitions animées entre différentes vues d'un site web. Elles constituent un choix de conception populaire pour préserver la continuité visuelle lorsque les visiteurs se déplacent entre les états ou les vues d'une application.

Les transitions de vue et la prise en charge du routage côté client d'Astro sont alimentées par l'[API des Transitions de Vue du navigateur](https://developer.chrome.com/docs/web-platform/view-transitions/) et incluent également :

- Quelques [options d'animation intégrées](#directives-danimation-intégrées), telles que `fade`, `slide` et `none`.
- La prise en charge des animations de navigation vers l'avant et vers l'arrière.
- La possibilité de [personnaliser entièrement tous les aspects de l'animation de transition](#personnalisation-des-animations) et de créer vos propres animations.
- Un moyen de transporter des éléments HTML de la page actuelle à la suivante pendant la navigation.
- L'option d'[empêcher la navigation côté client pour les liens qui ne sont pas des pages](#contrôle-du-routeur).
- Le [contrôle du comportement de repli](#contrôle-de-la-stratégie-de-repli) pour les navigateurs qui ne prennent pas encore en charge les API de Transition de Vue.
- La prise en charge automatique de [`prefers-reduced-motion`](#prefers-reduced-motion).

:::note
Par défaut, chaque page utilise la navigation normale, pleine page, du navigateur. Vous devez accepter d'afficher les transitions et pouvez les utiliser soit par page, soit sur l'ensemble du site.
:::

## Différences entre les transitions de vue natives du navigateur et le `<ClientRouter />` d'Astro

Les [transitions de vue inter-documents natives du navigateur](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API/Using#basic_mpa_view_transition) peuvent être utilisées dans Astro pour animer la navigation entre les documents dans une application multipage (MPA), offrant souvent l'expérience du routage côté client d'applications monopages. Elles ne modifient pas les fonctionnalités principales d'une application multipage, n'affectent pas les scripts existants et n'ajoutent pas de code JavaScript supplémentaire au chargement de la page. Elles ajoutent simplement des animations.

Pour des fonctionnalités améliorées de routage côté client et de transition de vue qui ne sont pas encore entièrement prises en charge par l'API de transition de vue, Astro fournit un composant léger intégré pour activer le routage côté client et transformer votre application multipage en une [application monopage](#activation-des-transitions-de-vue-mode-spa) avec des animations fluides lors de la navigation.

Cela présente certains avantages, comme l’état partagé entre les pages et les éléments persistants, et certains inconvénients, comme la nécessité de réinitialiser manuellement les scripts ou l’état après la navigation.

L'ajout du composant intégré `<ClientRouter />` d'Astro :
- [intercepte la navigation de la page](#processus-de-navigation-du-côté-client) et vous donne un contrôle considérable sur ce processus.
- étend et améliore certaines fonctionnalités des API de transition de vue/navigation.
- vous permet de [configurer des stratégies de repli](#contrôle-de-la-stratégie-de-repli) lorsque [la prise en charge native du navigateur fait défaut](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API#browser_compatibility).

Cependant, à mesure que les API des navigateurs et les standards Web évoluent, l'utilisation du routage côté client d'Astro (`<ClientRouter />`) pour cette fonctionnalité supplémentaire [deviendra de plus en plus inutile](https://astro.build/blog/future-of-astro-zero-js-view-transitions/). Nous vous recommandons de vous tenir informé de l'état actuel des API des navigateurs afin de [déterminer si vous avez toujours besoin du routage côté client d'Astro](https://events-3bg.pages.dev/jotter/astro-view-transitions/) pour les fonctionnalités que vous utilisez.

## Activation des transitions de vue (mode SPA)

Importez et ajoutez le composant `<ClientRouter />` à votre en-tête (`<head>`) commun ou à votre composant de mise en page partagé. Astro créera des animations de page par défaut en fonction des similitudes entre l'ancienne et la nouvelle page, et fournira également un comportement de repli pour les navigateurs non pris en charge.

L'exemple ci-dessous montre l'ajout des animations de navigation par défaut d'Astro sur l'ensemble du site, y compris l'option de contrôle de repli par défaut pour les navigateurs non compatibles, en important et en ajoutant ce composant à un composant Astro `<CommonHead />` :

```astro title="src/components/CommonHead.astro" ins={2,12}
---
import { ClientRouter } from "astro:transitions";
---
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />

<!-- Balises méta principales -->
<title>{title}</title>
<meta name="title" content={title} />
<meta name="description" content={description} />

<ClientRouter />
```

Aucune autre configuration n'est nécessaire pour activer la navigation côté client par défaut d'Astro !

Utilisez les [directives de transition](#directives-de-transition) ou [remplacer la navigation par défaut côté client](#empêcher-la-navigation-côté-client) sur des éléments individuels pour un contrôle plus fin.

## Directives de transition

Astro attribuera automatiquement aux éléments correspondants trouvés à la fois dans l'ancienne et la nouvelle page un nom unique et partagé `view-transition-name`. Cette paire d'éléments correspondants est déduite à la fois du type d'élément et de son emplacement dans le DOM.

Utilisez les directives optionnelles `transition:*` sur les éléments de page dans vos composants `.astro` pour un contrôle plus fin du comportement de transition de la page pendant la navigation.

- `transition:name` : Permet d'outrepasser la correspondance d'éléments par défaut d'Astro pour l'animation du contenu ancien/nouveau et de [spécifier un nom de transition](#nommer-une-transition) pour associer une paire d'éléments DOM.
- `transition:animate` : Permet d'outrepasser l'animation par défaut d'Astro tout en remplaçant l'ancien élément par le nouveau en spécifiant un type d'animation. Utilisez les [directives d'animation intégrées](#directives-danimation-intégrées) d'Astro ou [créer des animations de transition personnalisées](#personnalisation-des-animations).
- `transition:persist` : Permet d'outrepasser le remplacement par défaut des anciens éléments par de nouveaux et de [conserver les composants et les éléments HTML](#maintenir-létat) lorsque l'on navigue vers une autre page.

### Nommer une transition

Dans certains cas, vous souhaiterez ou devrez peut-être identifier vous-même les éléments de transition de vue correspondants. Vous pouvez spécifier un nom pour une paire d'éléments en utilisant la directive `transition:name`.

```astro title="src/pages/page-precedente.astro"
<aside transition:name="hero">
```

```astro title="src/pages/nouvelle-page.astro"
<aside transition:name="hero">
```

Notez que la valeur `transition:name` fournie ne peut être utilisée qu'une seule fois par page. Définissez cette valeur manuellement lorsque Astro ne peut pas déduire lui-même un nom approprié, ou pour un contrôle plus fin des éléments correspondants.

### Maintenir l'état

<p><Since v="2.10.0" /></p>

Vous pouvez faire persister les composants et les éléments HTML (au lieu de les remplacer) à travers les pages naviguées en utilisant la directive `transition:persist`.

Par exemple, la `<video>` suivante continuera à être lue lorsque vous naviguerez au sein d'une autre page contenant le même élément vidéo. Cela fonctionne aussi bien pour la navigation vers l'avant que vers l'arrière.

```astro title="src/components/Video.astro" "transition:persist"
<video controls muted autoplay transition:persist>
  <source
    src="https://ia804502.us.archive.org/33/items/GoldenGa1939_3/GoldenGa1939_3_512kb.mp4"
    type="video/mp4"
  />
</video>
```

Vous pouvez également placer la directive sur un [îlot Astro](/fr/concepts/islands/) (un framework UI avec une directive [`client:`](/fr/reference/directives-reference/#directives-client)). Si ce composant existe sur la page suivante, l'îlot de l'ancienne page **avec son état actuel** continuera d'être affichée, au lieu d'être remplacée par l'îlot de la nouvelle page.

Dans l'exemple ci-dessous, l'état interne du compteur du composant ne sera pas réinitialisé lors de la navigation entre les pages qui contiennent le composant `<Counter />` avec l'attribut `transition:persist`.

```astro title="src/components/Header.astro" "transition:persist"
<Counter client:load transition:persist initialCount={5} />
```

:::note[Limitations connues]
Tous les états ne peuvent pas être préservés de cette manière. Le redémarrage des animations CSS et le rechargement des iframes ne peuvent être évités lors des transitions de vue, même en utilisant `transition:persist`.
:::

Vous pouvez également [identifier manuellement les éléments correspondants](#nommer-une-transition) si l'îlot/l'élément se trouve dans un composant différent entre les deux pages.

```astro title="src/pages/page-precedente.astro" "video" 'transition:name="media-player"'
<video
  controls
  muted
  autoplay
  transition:name="media-player"
  transition:persist
/>
```

```astro title="src/pages/nouvelle-page.astro" "MyVideo" 'transition:name="media-player"'
<MyVideo
  controls
  muted
  autoplay
  transition:name="media-player"
  transition:persist
/>
```

Comme raccourci pratique, `transition:persist` peut aussi prendre un nom de transition comme valeur.

```astro title="src/pages/index.astro" 'transition:persist="media-player"'
<video controls muted autoplay transition:persist="media-player">
```

#### `transition:persist-props`

<p><Since v="4.5.0" /></p>

Cela vous permet de contrôler si les props d'un îlot doivent ou non être conservées lors de la navigation.

Par défaut, lorsque vous ajoutez `transition:persist` à un îlot, l'état est conservé lors de la navigation, mais votre composant sera à nouveau rendu avec de nouvelles props. Ceci est utile, par exemple, lorsqu'un composant reçoit des props spécifiques à une page, comme le titre (`title`) de la page courante.

Vous pouvez modifier ce comportement en définissant `transition:persist-props` en plus de `transition:persist`. L'ajout de cette directive conservera les props existantes d'un îlot (sans le restituer avec de nouvelles valeurs) en plus de maintenir son état existant.

### Directives d'animation intégrées

Astro est livré avec quelques animations intégrées pour remplacer la transition par défaut `fade`. Ajoutez la directive `transition:animate` à des éléments individuels pour personnaliser le comportement de transitions spécifiques.

- `fade` (par défaut) : Une animation de fondu enchaîné. L'ancien contenu disparaît et le nouveau contenu apparaît en fondu.
- `initial` : Permet de ne pas utiliser l'animation de fondu enchaîné d'Astro et d'utiliser le style par défaut du navigateur.
- `slide` : Une animation où l'ancien contenu glisse vers la gauche et le nouveau contenu glisse vers la droite. En navigation arrière, les animations sont inversées.
- `none` : Désactive les animations par défaut du navigateur. À utiliser sur l'élément `<html>` d'une page pour désactiver le fondu par défaut pour tous les éléments de la page.

Combinez les directives pour un contrôle total de l'animation de votre page. Définissez une page par défaut sur l'élément `<html>`, et modifiez les éléments individuels comme vous le souhaitez.

L'exemple ci-dessous produit une animation de diapositive pour le corps du texte tout en désactivant l'animation de fondu par défaut du navigateur pour le reste de la page :

```astro
---
import CommonHead from "../components/CommonHead.astro";
---

<html transition:name="root" transition:animate="none">
  <head>
    <CommonHead />
  </head>
  <body>
    <header>
      ...
    </header>
    <!-- Remplace la valeur par défaut de votre page par un seul élément -->
    <main transition:animate="slide">
      ...
    </main>
  </body>
</html>
```

### Personnalisation des animations

Vous pouvez personnaliser tous les aspects d'une transition avec n'importe quelle propriété d'animation CSS.

Pour personnaliser une animation intégrée, il faut d'abord importer l'animation depuis `astro:transitions`, puis passer les options de personnalisation.

L'exemple ci-dessous personnalise la durée de l'animation intégrée `fade` :

```astro
---
import { fade } from "astro:transitions";
---
<header transition:animate={fade({ duration: "0.4s" })}>
```

Vous pouvez également définir vos propres animations à utiliser avec `transition:animate` en définissant le comportement en avant et en arrière, ainsi que les nouvelles et les anciennes pages, selon les types suivants :

```ts
export interface TransitionAnimation {
  name: string; // Nom de l'image clé
  delay?: number | string;
  duration?: number | string;
  easing?: string;
	fillMode?: string;
	direction?: string;
}

export interface TransitionAnimationPair {
	old: TransitionAnimation | TransitionAnimation[];
	new: TransitionAnimation | TransitionAnimation[];
}

export interface TransitionDirectionalAnimations {
	forwards: TransitionAnimationPair;
	backwards: TransitionAnimationPair;
}
```

L'exemple suivant montre toutes les propriétés nécessaires pour définir une animation `bump` personnalisée à l'intérieur d'une balise `<style is:global>` dans votre fichier de mise en page racine :

```astro title="src/layouts/Layout.astro"
---
import { ClientRouter } from "astro:transitions";
---
<html lang="en">
  <head>
    <ClientRouter />
  </head>
  <body>
    <slot />
  </body>
</html>

<style is:global>
  @keyframes bump {
    0% {
      opacity: 0;
      transform: scale(1) translateX(200px);
    }
    50% {
      opacity: 0.5;
      transform: scale(1.1);
    }
    100% {
      opacity: 1;
      transform: scale(1) translateX(0);
    }
  }
</style>
```

Le comportement de l'animation doit être défini dans le frontmatter de chaque composant utilisant l'animation :

```astro title="src/pages/index.astro"
---
const anim = {
  old: {
    name: "bump",
    duration: "0.5s",
    easing: "ease-in",
    direction: "reverse",
  },
  new: {
    name: "bump",
    duration: "0.5s",
    easing: "ease-in-out",
  },
};

const customTransition = {
  forwards: anim,
  backwards: anim,
};
---
<header transition:animate={customTransition}> ... </header>
```

Vous disposez d'une grande flexibilité pour définir des animations personnalisées. Pour obtenir le résultat souhaité, vous pouvez envisager des combinaisons inhabituelles, telles qu'utiliser des objets différents pour les propriétés `forwards` et `backwards`, ou fournir des étapes d'animations distinctes pour les propriétés `old` et `new`.

## Contrôle du routeur

Le routeur `<ClientRouter />` gère la navigation en observant :

- les clics sur les éléments `<a>`.
- les événements de navigation vers l'avant et vers l'arrière.

Les options suivantes vous permettent de contrôler davantage le moment où la navigation s'effectue dans le routeur :

- `data-astro-reload` : un attribut de balise `<a>` pour [forcer une navigation pleine page](#empêcher-la-navigation-côté-client)
- `data-astro-history="auto | push | replace"` : un attribut de balise `<a>` pour [contrôler l'historique du navigateur](#remplacer-les-entrées-dans-lhistorique-du-navigateur)
- `navigate(href, options)` : une méthode disponible pour n'importe quel script ou composant client pour [déclencher la navigation](#déclenchement-de-la-navigation)

### Empêcher la navigation côté client

Dans certains cas, il n'est pas possible de naviguer via le routage côté client, car les deux pages concernées doivent utiliser le routeur `<ClientRouter />` pour éviter un rechargement complet de la page. Il se peut également que vous ne souhaitiez pas un routage côté client à chaque changement de navigation et que vous préfériez une navigation de page traditionnelle sur des itinéraires sélectionnés.

Vous pouvez renoncer au routage côté client pour chaque lien en ajoutant l'attribut `data-astro-reload` à n'importe quelle balise `<a>` ou `<form>`. Cet attribut remplacera tout composant `<ClientRouter />` existant et déclenchera à la place un rafraîchissement du navigateur pendant la navigation.

L'exemple suivant montre comment empêcher le routage côté client lors de la navigation vers un article depuis la page d'accueil uniquement. Cela permet néanmoins d'animer des éléments partagés, tels qu'une image de héros, lors de la navigation vers la même page à partir d'une page de liste d'articles :

```astro title="src/pages/index.astro"
<a href="/articles/emperor-penguins" data-astro-reload>
```

```astro title="src/pages/articles.astro"
<a href="/articles/emperor-penguins">
```

Les liens avec l'attribut `data-astro-reload` seront ignorés par le routeur et une navigation pleine page se produira.

### Déclenchement de la navigation

Vous pouvez aussi déclencher la navigation côté client via des événements qui ne sont pas normalement écoutés par le routeur `<ClientRouter />` en utilisant [`navigate()`](/fr/reference/modules/astro-transitions/#navigate). Cette fonction du module `astro:transitions/client` peut être utilisée dans les scripts et dans les composants du framework qui sont hydratés avec une [directive client](/fr/reference/directives-reference/#directives-client).

L'exemple suivant montre un composant Astro qui permet à un visiteur de naviguer vers une autre page qu'il sélectionne dans un menu :

```astro title="src/components/Form.astro"
<script>
  import { navigate } from "astro:transitions/client";

  // Naviguer automatiquement vers l'option sélectionnée.
  document.querySelector("select").onchange = (event) => {
    let href = event.target.value;
    navigate(href);
  };
</script>
<select>
  <option value="/play">Jouer</option>
  <option value="/blog">Blog</option>
  <option value="/about">A propos</option>
  <option value="/contact">Contact</option>
</select>
```

```astro title="src/pages/index.astro"
---
import Form from "../components/Form.astro";
import { ClientRouter } from "astro:transitions";
---
<html>
	<head>
		<ClientRouter />
	</head>
	<body>
		<Form />
	</body>
</html>
```

L'exemple suivant met en œuvre la même chose en utilisant `navigate()` dans un composant React `<Form />` :

```js title="src/components/Form.jsx"
import { navigate } from 'astro:transitions/client';

export default function Form() {
  return (
    <select onChange={(e) => navigate(e.target.value)}>
      <option value="/play">Jouer</option>
      <option value="/blog">Blog</option>
      <option value="/about">A propos</option>
      <option value="/contact">Contact</option>
    </select>
  );
}
```

Le composant `<Form />` peut alors être rendu sur une page Astro qui utilise le routeur `<ClientRouter />`, avec une directive client :

```astro title="src/pages/index.astro"
---
import Form from "../components/form.jsx";
import { ClientRouter } from "astro:transitions";
---
<html>
	<head>
		<ClientRouter />
	</head>
	<body>
		<Form client:load />
	</body>
</html>
```

Pour la navigation vers l'arrière et vers l'avant dans l'historique du navigateur, vous pouvez combiner `navigate()` avec les fonctions intégrées `history.back()`, `history.forward()` et `history.go()` du navigateur. Si `navigate()` est appelée pendant le rendu côté serveur de votre composant, elle n'a aucun effet.

<ReadMore>Consultez la référence d'`astro:transitions` pour plus d'informations sur les options de [`navigate()`](/fr/reference/modules/astro-transitions/#navigate).</ReadMore>

### Remplacer les entrées dans l'historique du navigateur

Normalement, à chaque navigation, une nouvelle entrée est ajoutée à l'historique du navigateur. Cela permet de naviguer entre les pages à l'aide des boutons « Précédent » et « Suivant ».

Le routeur `<ClientRouter />` vous permet d'écraser les entrées de l'historique en ajoutant l'attribut `data-astro-history` à n'importe quelle balise `<a>`.

L'attribut `data-astro-history` peut être défini avec les trois mêmes valeurs que l'option [`history` de la fonction `navigate()`](/fr/reference/modules/astro-transitions/#option-history) :

- `"push"` : le routeur utilisera `history.pushState` pour créer une nouvelle entrée dans l'historique du navigateur.
- `"replace"` : le routeur utilisera `history.replaceState` pour mettre à jour l'URL sans ajouter une nouvelle entrée dans la navigation.
- `"auto"` (par défaut) : le routeur tentera `history.pushState`, mais si l'URL n'est pas une URL vers laquelle il est possible d'effectuer une transition, l'URL actuelle sera conservée sans modification de l'historique du navigateur.

L'exemple suivant navigue vers la page `/main` mais n'ajoute pas une nouvelle entrée à l'historique de navigation. Au lieu de cela, il réutilise l'entrée actuelle dans l'historique (`/confirmation`) et l'écrase.

```astro title="src/pages/confirmation.astro"
<a href="/main" data-astro-history="replace">
```

Cela a pour effet que si vous revenez en arrière à partir de la page `/main`, le navigateur n'affichera pas la page `/confirmation`, mais la page qui la précède.

### Transitions avec les formulaires

<p><Since v="4.0.0" /></p>

Le routeur `<ClientRouter />` déclenche des transitions dans la page à partir d'éléments `<form>`, supportant à la fois les requêtes `GET` et `POST`.

Par défaut, Astro envoie les données de votre formulaire en tant que `multipart/form-data` lorsque votre méthode (`method`) est définie sur `POST`. Si vous voulez correspondre au comportement par défaut des navigateurs web, utilisez l'attribut `enctype` pour soumettre vos données encodées en tant que `application/x-www-form-urlencoded` :

```astro title="src/components/Form.astro"
<form
  action="/contact"
  method="POST"
  enctype="application/x-www-form-urlencoded"
>
```

Vous pouvez refuser les transitions de routeur sur un formulaire individuel en utilisant l'attribut `data-astro-reload` :

```astro title="src/components/Form.astro"
<form action="/contact" data-astro-reload>
```

### Naviguer en utilisant la saisie de l'utilisateur

L'API `navigate()` n'effectue aucun nettoyage des URL qui lui sont transmises. Si vous utilisez les données saisies par l'utilisateur pour déterminer l'URL vers laquelle naviguer, vous devez valider ces données avant de les transmettre à `navigate()`.

Par exemple, un paramètre de requête `?redirect` pourrait être utilisé pour naviguer hors de votre site (`?redirect=http://example.com`) ou pour exécuter du code arbitraire (`?redirect=javascript:alert('Code malveillant')`) si la valeur n'est pas nettoyée avant utilisation.

Une façon de mettre cela en œuvre en toute sécurité consiste à s'assurer que la redirection n'est possible que pour une série de chemins connus :

```astro title="src/pages/index.astro"
<script>
  import { navigate } from 'astro:transitions/client';

  const params = new URLSearchParams(window.location.search);
  const redirect = params.get('redirect');
  const allowedPaths = ['/home', '/a-propos', '/contact'];

  if (allowedPaths.includes(redirect)) {
    navigate(redirect);
  }
</script>
```

Le type exact de nettoyage dont vous aurez besoin dépendra de votre site et de ce que vous souhaitez autoriser.

<ReadMore>Envisagez d’activer la [fonctionnalité expérimentale de politique de sécurité du contenu](/fr/reference/experimental-flags/csp/) d’Astro pour vous protéger contre les risques de script intersite (XSS) si vous utilisez la saisie des utilisateurs avec l’API `navigate()`.</ReadMore>

## Contrôle de la stratégie de repli

Le routeur `<ClientRouter />` fonctionne mieux dans les navigateurs qui prennent en charge les Transitions de Vue (c'est-à-dire les navigateurs Chromium), mais inclut également par défaut une stratégie de repli pour les autres navigateurs. Même si le navigateur ne prend pas en charge l'API des Transitions de Vue, le routeur client d'Astro peut tout de même assurer la navigation dans le navigateur grâce à l'une des options de repli.

En fonction de la prise en charge du navigateur, vous devrez peut-être définir explicitement les [directives de transition](#directives-de-transition) `name` ou `animate` sur les éléments que vous souhaitez animer pour une expérience comparable sur tous les navigateurs :

```astro title="src/pages/about.astro"
---
import Layout from "../layouts/LayoutUsingClientRouter.astro";
---
<title transition:animate="fade">À propos de mon site</title>
```

Vous pouvez remplacer la stratégie de repli par défaut d'Astro en ajoutant une propriété `fallback` sur le composant `<ClientRouter />` et en la définissant sur `swap` ou `none` :

- `animate` (par défaut, recommandé) : Astro simulera des transitions de vues en utilisant des attributs personnalisés avant de mettre à jour le contenu de la page.
- `swap` : Astro n'essaiera pas d'animer la page. Au lieu de cela, l'ancienne page sera immédiatement remplacée par la nouvelle.
- `none` : Astro n'effectuera aucune transition de page animée. Au lieu de cela, vous obtiendrez une navigation pleine page dans les navigateurs qui ne la supportent pas.

```astro
---
import { ClientRouter } from "astro:transitions";
---
<title>Mon site</title>

<ClientRouter fallback="swap" />
```

:::note[Limitations connues]
L'animation `initiale` du navigateur n'est pas simulée par Astro. Par conséquent, tout élément utilisant cette animation ne sera pas animé pour le moment.
:::

## Processus de navigation du côté client

Lors de l'utilisation du routeur `<ClientRouter />`, les étapes suivantes se produisent pour produire la navigation côté client d'Astro :

<Steps>
1. Un visiteur de votre site déclenche la navigation par l'une des actions suivantes :
   - En cliquant sur une balise `<a>` qui renvoie à une autre page de votre site.
   - En cliquant sur le bouton « Précédent ».
   - En cliquant sur le bouton « Suivant ».
2. Le routeur commence à récupérer la page suivante.
3. Le routeur ajoute l'attribut `data-astro-transition` à l'élément HTML avec la valeur `"forward"` ou `"back"` selon le cas.
4. Le routeur appelle `document.startViewTransition`. Cela déclenche le [processus de Transition de Vue du navigateur](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API/Using#the_view_transition_process). Il est important de noter que le navigateur fait une capture d'écran de l'état actuel de la page.
5. Dans le callback `startViewTransition`, le routeur effectue un __swap__, qui consiste en la séquence d'événements suivante :

    - Le contenu du `<head>` est remplacé, certains éléments étant conservés :
      - Les nœuds DOM des feuilles de style sont conservés s'ils existent sur la nouvelle page, afin d'éviter les FOUC.
      - Les scripts sont conservés s'ils existent sur la nouvelle page.
      - Tous les autres éléments d'en-tête avec `transition:persist` sont conservés s'il existe un élément correspondant dans la nouvelle page.

    - Le `<body>` est complètement remplacé par le corps de la nouvelle page.

    - Les éléments marqués `transition:persist` sont déplacés vers le nouveau DOM s'ils existent sur la nouvelle page.

    - La position de défilement est restaurée si nécessaire.

    - L'événement `astro:after-swap` est déclenché sur le `document`. C'est la fin du processus de __swap__.

6. Le routeur attend le chargement de toute nouvelle feuille de style avant de résoudre la transition.
7. Le routeur exécute tous les nouveaux scripts ajoutés à la page.
8. L'événement `astro:page-load` se déclenche. C'est la fin du processus de navigation.
</Steps>

## Comportement du script avec les transitions de vue

Lorsque vous ajoutez des transitions de vue à un projet Astro existant, il se peut que certains de vos scripts ne s'exécutent plus après la navigation dans la page, comme c'était le cas lors de l'actualisation complète du navigateur. Utilisez les informations suivantes pour vous assurer que vos scripts s'exécutent comme prévu.

### Ordre de script

Lorsque l'on navigue entre les pages avec le composant `<ClientRouter />`, les scripts sont exécutés dans un ordre séquentiel pour correspondre au comportement du navigateur.

### Réexécution du script

Les [scripts des modules intégrés](/fr/guides/client-side-scripts/#traitement-des-scripts), qui sont les scripts par défaut dans Astro, ne sont exécutés qu'une seule fois. Après l'exécution initiale, ils seront ignorés, même si le script existe sur la nouvelle page après une transition.

Contrairement aux scripts de modules intégrés, les [scripts incorporés à la page](/fr/guides/client-side-scripts/#scripts-non-traités) peuvent être réexécutés au cours de la visite d'un utilisateur sur un site s'ils se trouvent sur une page visitée plusieurs fois. Les scripts incorporés à la page peuvent également être réexécutés lorsqu'un visiteur navigue vers une page sans script, puis de nouveau vers une page avec le script.

Avec les transitions de vue, certains scripts peuvent ne plus être réexécutés après la navigation vers une nouvelle page comme c'est le cas avec les actualisations complètes du navigateur. Il existe plusieurs [événements pendant le routage côté client que vous pouvez écouter](#événements-du-cycle-de-vie) et déclencher des événements lorsqu'ils se produisent. Vous pouvez encapsuler un script existant dans un écouteur d'événements pour garantir qu'il s'exécute au bon moment dans le cycle de navigation.

L'exemple suivant encapsule un script pour un menu mobile « hamburger » dans un écouteur d'événement pour `astro:page-load` qui s'exécute à la fin de la navigation dans la page pour rendre le menu réactif lorsqu'on clique dessus après la navigation vers une nouvelle page :

```js title="src/scripts/menu.js" ins={1,5}
document.addEventListener("astro:page-load", () => {
  document.querySelector(".hamburger").addEventListener("click", () => {
    document.querySelector(".nav-links").classList.toggle("expanded");
  });
});
```

L'exemple suivant montre une fonction qui s'exécute en réponse à l'événement `astro:after-swap`, qui se produit immédiatement après que la nouvelle page a remplacé l'ancienne page et avant que les éléments DOM ne soient affichés à l'écran. Cela permet d'éviter un flash du thème en mode clair après la navigation dans la page en vérifiant et, si nécessaire, en définissant le thème en mode sombre avant le rendu de la nouvelle page :

```astro title="src/components/ThemeToggle.astro"
<script is:inline>
  function applyTheme() {
    localStorage.theme === "dark" 
      ? document.documentElement.classList.add("dark")
      : document.documentElement.classList.remove("dark");
  }

  document.addEventListener("astro:after-swap", applyTheme);
  applyTheme(); 
</script>
```

#### `data-astro-rerun`

<p><Since v="4.5.0" /></p>

Pour forcer les scripts incorporés à la page à se réexécuter après chaque transition, ajoutez la propriété `data-astro-rerun`. L'ajout de n'importe quel attribut à un script ajoute aussi implicitement `is:inline`, donc ceci n'est disponible que pour les scripts qui ne sont pas regroupés et traités par Astro.

```astro
<script is:inline data-astro-rerun>...</script>
```

Pour garantir qu'un script s'exécute à chaque fois qu'une page est chargée pendant la navigation côté client, il doit être exécuté par un [événement de cycle de vie](#événements-du-cycle-de-vie). Par exemple, les récepteurs d'événements pour `DOMContentLoaded` peuvent être remplacés par l'événement de cycle de vie [`astro:page-load`](/fr/guides/view-transitions/#astropage-load).

Si vous avez du code qui établit un état global dans un script incorporé à la page, cet état devra prendre en compte le fait que le script peut s'exécuter plus d'une fois. Vérifiez l'état global dans votre balise `<script>`, et exécutez votre code de manière conditionnelle lorsque c'est possible. Cela fonctionne parce que `window` est préservé.

```astro
<script is:inline>
  if (!window.SomeGlobal) {
    window.SomeGlobal = {};
  }
</script>
```

## Événements du cycle de vie

Le routeur `<ClientRouter />` déclenche un certain nombre d'événements sur le `document` pendant la navigation. Ces événements fournissent des crochets dans le cycle de vie de la navigation, vous permettant de faire des choses comme montrer des indicateurs qu'une nouvelle page est en train de se charger, surcharger le comportement par défaut, et restaurer l'état lorsque la navigation se termine.

Le processus de navigation comprend une phase de **préparation**, au cours de laquelle le nouveau contenu est chargé ; une phase d'**échange de DOM**, au cours de laquelle le contenu de l'ancienne page est remplacé par celui de la nouvelle ; et une phase d'**achèvement**, au cours de laquelle les scripts sont exécutés, le chargement est signalé comme étant terminé et le travail de nettoyage est effectué.

Les événements du cycle de vie de l'API de transition de vue d'Astro sont, dans l'ordre, les suivants :

- [`astro:before-preparation`](#astrobefore-preparation)
- [`astro:after-preparation`](#astroafter-preparation)
- [`astro:before-swap`](#astrobefore-swap)
- [`astro:after-swap`](#astroafter-swap)
- [`astro:page-load`](#astropage-load)

:::tip
Les événements `before-` vous permettent d'influencer et de modifier les actions qui sont sur le point d'avoir lieu, et les événements `after-` sont des notifications indiquant qu'une phase est terminée.
:::

Si certaines actions peuvent être déclenchées lors de n'importe quel événement, d'autres tâches ne peuvent être exécutées que lors d'un événement spécifique pour obtenir les meilleurs résultats, comme l'affichage d'une barre de chargement avant la préparation ou la modification des paires d'animations avant le changement de contenu.

### `astro:before-preparation`

<p><Since v="3.6.0" /></p>

Un événement qui se déclenche au début de la phase de préparation, après que la navigation a commencé (par exemple, après que l'utilisateur a cliqué sur un lien), mais avant que le contenu ne soit chargé.

Cet événement est utilisé :

- Pour faire quelque chose avant que le chargement n'ait commencé, par exemple afficher un indicateur de chargement.
- Pour modifier le chargement, comme charger le contenu que vous avez défini dans un modèle plutôt qu'à partir de l'URL externe.
- Pour changer la `direction` de la navigation (qui est généralement soit `forward` soit `backward`) pour une animation personnalisée.

Voici un exemple d'utilisation de l'événement `astro:before-preparation` pour afficher un indicateur de chargement avant que le contenu ne soit chargé et le faire disparaître immédiatement après. Notez que l'utilisation de la [fonction de rappel `loader`](/fr/reference/modules/astro-transitions/#loader) de cette manière permet l'exécution asynchrone du code.

```astro
<script is:inline>
  document.addEventListener("astro:before-preparation", (event) => {
    const originalLoader = event.loader;
    event.loader = async function () {
      const { startSpinner } = await import("./spinner.js");
      const stop = startSpinner();
      await originalLoader();
      stop();
    };
  });
</script>
```

### `astro:after-preparation`

<p><Since v="3.6.0" /></p>

Événement qui se déclenche à la fin de la phase de préparation, après que le contenu de la nouvelle page a été chargé et analysé dans un document. Cet événement se produit avant la phase de transition des vues.

Cet exemple utilise l'événement `astro:before-preparation` pour démarrer un indicateur de chargement et l'événement `astro:after-preparation` pour l'arrêter :

```astro
<script is:inline>
  document.addEventListener("astro:before-preparation", () => {
    document.querySelector("#loading").classList.add("show");
  });
  document.addEventListener("astro:after-preparation", () => {
    document.querySelector("#loading").classList.remove("show");
  });
</script>
```

Il s'agit d'une version plus simple du chargement d'un spinner que l'exemple ci-dessus : si tout le code de l'écouteur peut être exécuté de manière synchrone, il n'est pas nécessaire de se connecter au callback du chargeur (`loader`).

### `astro:before-swap`

<p><Since v="3.6.0" /></p>

Événement qui se déclenche avant que le nouveau document (qui est rempli pendant la phase de préparation) ne remplace le document actuel. Cet événement se produit à l'intérieur de la transition de vue, où l'utilisateur voit encore un instantané de l'ancienne page.

Cet événement peut être utilisé pour effectuer des modifications avant que la permutation ne se produise. La propriété `newDocument` de l'événement représente le document entrant. Voici un exemple permettant de s'assurer que les préférences du navigateur en matière de mode clair ou foncé dans `localStorage` sont reportées sur la nouvelle page :

```astro
<script>
  document.addEventListener("astro:before-swap", (event) => {
    event.newDocument.documentElement.dataset.theme =
      localStorage.getItem("darkMode") ? "dark" : "light";
  });
</script>
```

L'événement `astro:before-swap` peut aussi être utilisé pour changer l'*implémentation* de la permutation. L'implémentation par défaut de la permutation diffère le contenu de l'en-tête, déplace les éléments __persistants__ de l'ancien document vers `newDocument`, et remplace ensuite l'ensemble du corps (`body`) par celui du nouveau document.

À ce stade du cycle de vie, vous pouvez choisir de définir votre propre implémentation de l'échange, par exemple pour diffuser l'intégralité du contenu du document existant (ce que font certains autres routeurs) :

```astro
<script is:inline>
  document.addEventListener("astro:before-swap", (event) => {
    event.swap = () => {
      diff(document, event.newDocument);
    };
  });
</script>
```

#### Créer une fonction d'échange personnalisée

<p><Since v="4.15.0" /></p>

L'[objet `swapFunctions`](/fr/reference/modules/astro-transitions/#swapfunctions) du module `astro:transitions/client` fournit cinq fonctions utilitaires qui gèrent des tâches spécifiques liées à l'échange, notamment la gestion des attributs de document, des éléments de page et l'exécution de scripts. Ces fonctions peuvent être utilisées directement pour définir une implémentation d'échange personnalisée.

L'exemple suivant montre comment utiliser ces fonctions pour recréer l'implémentation d'échange intégrée d'Astro :

```astro
<script>
  import { swapFunctions } from "astro:transitions/client";
  
  // substitutes `window.document` with `doc`
  function mySwap(doc: Document) {
    swapFunctions.deselectScripts(doc);
    swapFunctions.swapRootAttributes(doc);
    swapFunctions.swapHeadElements(doc);
    const restoreFocusFunction = swapFunctions.saveFocus();
    swapFunctions.swapBodyElement(doc.body, document.body);
    restoreFocusFunction();
  }
  
  document.addEventListener("astro:before-swap", (event) => {
    event.swap = () => mySwap(event.newDocument);
  });
<script>
```

Les implémentations d'échange personnalisées peuvent commencer avec ce modèle et ajouter ou remplacer des étapes individuelles par une logique personnalisée selon les besoins.

### `astro:after-swap`

Un événement qui se déclenche immédiatement après que la nouvelle page ait remplacé l'ancienne. Vous pouvez écouter cet événement sur `document` et déclencher des actions qui se produiront avant le rendu des éléments DOM de la nouvelle page et l'exécution des scripts.

Cet événement, lorsqu'il est écouté sur la **page sortante**, est utile pour transmettre et restaurer tout état du DOM qui doit être transféré sur la nouvelle page.

Il s'agit du dernier point du cycle de vie où il est encore possible, par exemple, d'ajouter un nom de classe en mode sombre (`<html class="dark-mode">`), bien que vous puissiez souhaiter le faire dans un événement antérieur.

L'événement `astro:after-swap` se produit immédiatement après la mise à jour de l'historique du navigateur et la définition de la position de défilement.
Par conséquent, l'une des utilisations du ciblage de cet événement consiste à remplacer la restauration du défilement par défaut pour la navigation dans l'historique. L'exemple suivant réinitialise la position de défilement horizontale et verticale au coin supérieur gauche de la page pour chaque navigation.

```js
document.addEventListener("astro:after-swap", () =>
  window.scrollTo({ left: 0, top: 0, behavior: "instant" }),
);
```

### `astro:page-load`

Un événement qui se déclenche à la fin de la navigation de la page, après que la nouvelle page soit visible par l'utilisateur et que les styles et les scripts bloquants soient chargés. Vous pouvez écouter cet événement sur le `document`.

Le composant `<ClientRouter />` déclenche cet événement à la fois lors de la navigation initiale sur une page pré-rendue et lors de toute navigation ultérieure, que ce soit en avant ou en arrière.

Vous pouvez utiliser cet événement pour exécuter du code à chaque navigation de page, par exemple pour configurer des écouteurs d'événements qui autrement seraient perdus pendant la navigation.

```astro
<script>
  document.addEventListener("astro:page-load", () => {
    // Cette opération s'exécute lors du premier chargement de la page et après chaque navigation.
    setupStuff(); // par exemple, ajouter des écouteurs d'événements
  });
</script>
```

## Accessibilité

L'activation du routage côté client et l'animation des transitions de page posent toutes deux des problèmes d'accessibilité, et Astro vise à rendre les sites qui optent pour View Transitions aussi accessibles par défaut que possible.

### Annonce de la route

<p><Since v="3.2.0" /></p>

Le composant `<ClientRouter />` inclut un annonceur de route pour la navigation de page pendant le routage côté client. Aucune configuration ou action n'est nécessaire pour l'activer.

Les technologies d'assistance permettent aux visiteurs de savoir que la page a changé en annonçant le nouveau titre de la page après la navigation. Lors de l'utilisation du routage côté serveur avec un rafraîchissement traditionnel de la page entière du navigateur, cela se produit par défaut après le chargement de la nouvelle page. Dans le cas du routage côté client, c'est le composant `<ClientRouter />` qui effectue cette action.

Pour ajouter l'annonce d'itinéraire au routage côté client, le composant ajoute un élément à la nouvelle page avec l'attribut `aria-live` fixé à `assertive`. Cela indique à AT (technologie d'assistance) d'annoncer immédiatement. Le composant vérifie également les éléments suivants, par ordre de priorité, pour déterminer le texte de l'annonce :

- Le `<title>`, s'il existe.
- Le premier `<h1>` qu'il trouve.
- Le chemin de la page (`pathname`).

Nous vous recommandons vivement de toujours inclure un `<title>` dans chaque page pour des raisons d'accessibilité.

### `prefers-reduced-motion`

Le composant `<ClientRouter />` d'Astro inclut une requête média CSS qui désactive *toutes* les animations de transition de vue, y compris l'animation de secours, lorsque le paramètre [`prefer-reduced-motion`](https://developer.mozilla.org/fr/docs/Web/CSS/@media/prefers-reduced-motion) est détecté. À la place, le navigateur échangera simplement les éléments DOM sans animation.
